﻿#region Disclaimer/Info
///////////////////////////////////////////////////////////////////////////////////////////////////
// MetaCollection
// 
// MetaCollection is a system to provide a standard structure, permissions and metadata service
// for content organization.
//
// This project is hosted at Google Code at http://code.google.com/p/metacollection/
//
// This project is licensed under the BSD license.  See the License.txt file for more information.
///////////////////////////////////////////////////////////////////////////////////////////////////
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using MetaCollection.Framework.Model;
using MetaCollection.Framework.Repository;
using Moq;
using System.Linq.Expressions;
using MetaCollection.Framework.Change;
using MetaCollection.Framework.Security;

namespace MetaCollection.Framework.Tests.Fakes
{

	public class FakeItemRepository : IItemRepository
	{
		private List<IItemInstance> m_FakeItems;
		private List<IItemClaim> m_FakeClaims;
		private List<IItemProperty> m_FakeProps;
		private List<IItemRelationship> m_FakeRelations;
		private List<IProviderType> m_FakeProviderTypes;

		string m_RepoName;

		public void Initialize(string configData) { }

		public FakeItemRepository() : this(string.Empty) {}

		/// <summary>
		/// Initialize our Fake repository with a few items.
		/// </summary>
		public FakeItemRepository(string name)
		{
			m_RepoName = name;
			if (!string.IsNullOrEmpty(name))
				name = name + ":";
			m_FakeItems = new List<IItemInstance>();
			m_FakeClaims = new List<IItemClaim>();
			m_FakeProps = new List<IItemProperty>();
			m_FakeRelations = new List<IItemRelationship>();
			m_FakeProviderTypes = new List<IProviderType>();

			#region add fake relations

			var fakeRel = new Mock<IItemRelationship>();
			//fakeRel.Setup()
			//fakeRel.SetupProperty(p => p.Priority, 1);
			fakeRel.SetupProperty(p => p.TargetItem, new Uri("col://Root/{3F967C4A-7246-4fcb-B2DC-BF61CCEC4D1D}"));
			fakeRel.SetupProperty(p => p.RelationshipType, "requires");
			m_FakeRelations.Add(fakeRel.Object);

			#endregion

			#region add fake provider types

			var pType = new Mock<IProviderType>();
			pType.SetupProperty(p => p.AssemblyName, "AssemblyName");
			pType.SetupProperty(p => p.Config, "Config data");
			pType.SetupProperty(p => p.Name, "DefaultResourceType");
			pType.SetupProperty(p => p.TypeName, "TypeName");
			m_FakeProviderTypes.Add(pType.Object);

			#endregion

			#region add fake props
			var prop1 = new Mock<IItemProperty>();
			prop1.SetupProperty(p => p.KeyName, "key1");
			prop1.SetupProperty(p => p.KeyValue, "value1");
			m_FakeProps.Add(prop1.Object);

			var prop2 = new Mock<IItemProperty>();
			prop2.SetupProperty(p => p.KeyName, "key2");
			prop2.SetupProperty(p => p.KeyValue, "value2");
			m_FakeProps.Add(prop2.Object);

			var prop3 = new Mock<IItemProperty>();
			prop3.SetupProperty(p => p.KeyName, "key3");
			prop3.SetupProperty(p => p.KeyValue, "value3");
			m_FakeProps.Add(prop3.Object);
			#endregion

			#region add fake claims

			var fakeClaim1 = new Mock<IItemClaim>();
			fakeClaim1.SetupProperty(p => p.Id, Guid.NewGuid());
			fakeClaim1.SetupProperty(p => p.ClaimType, MetaPrincipal.RoleClaimType);
			fakeClaim1.SetupProperty(p => p.ClaimValue, "test-read");
			fakeClaim1.SetupProperty(p => p.Rights, AccessRights.AllReadType);
			m_FakeClaims.Add(fakeClaim1.Object);

			var fakeClaim2 = new Mock<IItemClaim>();
			fakeClaim2.SetupProperty(p => p.Id, Guid.NewGuid());
			fakeClaim2.SetupProperty(p => p.ClaimType, MetaPrincipal.RoleClaimType);
			fakeClaim2.SetupProperty(p => p.ClaimValue, "test-write");
			fakeClaim2.SetupProperty(p => p.Rights, AccessRights.AllWriteType);
			m_FakeClaims.Add(fakeClaim2.Object);

			var fakeClaim3 = new Mock<IItemClaim>();
			fakeClaim3.SetupProperty(p => p.Id, Guid.NewGuid());
			fakeClaim3.SetupProperty(p => p.ClaimType, MetaPrincipal.RoleClaimType);
			fakeClaim3.SetupProperty(p => p.ClaimValue, "test-full");
			fakeClaim3.SetupProperty(p => p.Rights, AccessRights.FullControl);
			m_FakeClaims.Add(fakeClaim3.Object);

			#endregion

			#region add fake items
			var item = new Mock<IItemInstance>();
			item.SetupProperty(p => p.Id, new Guid("{C11D81B4-524F-484b-9754-AD0E04691DD0}"));
			item.SetupProperty(p => p.Name, name + "MyNewItem");
			item.SetupProperty(p => p.LeftVersion, 1);
			item.SetupProperty(p => p.RightVersion, null);
			item.SetupProperty(p => p.Version, 1);
			item.SetupProperty(p => p.LastModified, DateTime.Now.AddMinutes(-100239));
			item.SetupProperty(p => p.MimeType, "application/x-folder");
			item.SetupProperty(p => p.ParentId, new Guid("{e87928a4-b0af-4a87-9d73-000aa12da10b}") );
			item.SetupProperty(p => p.Published, true);
			item.SetupProperty(p => p.Specification, new Guid("{9c1e39ab-3a8e-40fa-a3e9-0ba6b77b7c9e}"));
			item.SetupProperty(p => p.AccessClaims, m_FakeClaims);
			item.SetupProperty(p => p.Properties, m_FakeProps);
			item.SetupProperty(p => p.CreatedBy, "Me, Myself, and I");
			item.SetupProperty(p => p.Relationships, m_FakeRelations);
			m_FakeItems.Add(item.Object);

			var item1 = new Mock<IItemInstance>();
			item1.SetupProperty(p => p.Id, new Guid("{C11D81B4-524F-484b-9754-AD0E04691DD0}"));
			item1.SetupProperty(p => p.Name, name + "Root");
			item1.SetupProperty(p => p.LeftVersion, 1);
			item1.SetupProperty(p => p.RightVersion, null);
			item1.SetupProperty(p => p.Version, 2);
			item1.SetupProperty(p => p.LastModified, DateTime.Now.AddMinutes(-100200));
			item1.SetupProperty(p => p.MimeType, "application/x-folder");
			item1.SetupProperty(p => p.ParentId, Guid.Empty);
			item1.SetupProperty(p => p.Published, true);
			item1.SetupProperty(p => p.Specification, new Guid("{F2558069-0C73-47ba-9BA5-8E591A4EB3EA}"));
			item1.SetupProperty(p => p.AccessClaims, m_FakeClaims);
			item1.SetupProperty(p => p.Properties, m_FakeProps);
			item1.SetupProperty(p => p.Relationships, m_FakeRelations);
			m_FakeItems.Add(item1.Object);

			var item2 = new Mock<IItemInstance>();
			item2.SetupProperty(p => p.Id, new Guid("{9AF786C6-E138-45d2-B150-E51C989EE3D0}"));
			item2.SetupProperty(p => p.Name, name + "ChildOne");
			item2.SetupProperty(p => p.LeftVersion, null);
			item2.SetupProperty(p => p.RightVersion, null);
			item2.SetupProperty(p => p.Version, 1);
			item2.SetupProperty(p => p.LastModified, DateTime.Now.AddMinutes(-100000));
			item2.SetupProperty(p => p.MimeType, "application/x-folder");
			item2.SetupProperty(p => p.ParentId, Guid.Empty);
			item2.SetupProperty(p => p.ItemClaimId, new Guid("{7E117A1E-FEED-DEAD-BEEF-0A7A9D9ED396}"));
			item2.SetupProperty(p => p.Published, true);
			item2.SetupProperty(p => p.Specification, new Guid("{F2558069-0C73-47ba-9BA5-8E591A4EB3EA}"));
			item2.SetupProperty(p => p.AccessClaims, m_FakeClaims);
			item2.SetupProperty(p => p.Properties, m_FakeProps);
			m_FakeItems.Add(item2.Object);

			var item3 = new Mock<IItemInstance>();
			item3.SetupProperty(p => p.Id, new Guid("{EBD1B6C6-52F0-4dd0-AA6D-AC752E8BFD5C}"));
			item3.SetupProperty(p => p.Name, name + "ChildOneChild");
			item3.SetupProperty(p => p.LeftVersion, null);
			item3.SetupProperty(p => p.RightVersion, null);
			item3.SetupProperty(p => p.Version, 1);
			item3.SetupProperty(p => p.LastModified, DateTime.Now.AddMinutes(-1000));
			item3.SetupProperty(p => p.MimeType, "application/x-folder");
			item3.SetupProperty(p => p.ParentId, new Guid("{9AF786C6-E138-45d2-B150-E51C989EE3D0}"));
			item3.SetupProperty(p => p.Published, true);
			item3.SetupProperty(p => p.Specification, new Guid("{F2558069-0C73-47ba-9BA5-8E591A4EB3EA}"));
			item3.SetupProperty(p => p.AccessClaims, m_FakeClaims);
			item3.SetupProperty(p => p.Properties, m_FakeProps);
			m_FakeItems.Add(item3.Object);

			var item4 = new Mock<IItemInstance>();
			item4.SetupProperty(p => p.Id, new Guid("{3F967C4A-7246-4fcb-B2DC-BF61CCEC4D1D}"));
			item4.SetupProperty(p => p.Name, name + "Root");
			item4.SetupProperty(p => p.LeftVersion, null);
			item4.SetupProperty(p => p.RightVersion, null);
			item4.SetupProperty(p => p.Version, 1);
			item4.SetupProperty(p => p.LastModified, DateTime.Now.AddMinutes(-100050));
			item4.SetupProperty(p => p.MimeType, "text/plain");
			item4.SetupProperty(p => p.ParentId, new Guid("{C11D81B4-524F-484b-9754-AD0E04691DD0}"));
			item4.SetupProperty(p => p.Published, true);
			item4.SetupProperty(p => p.Specification, new Guid("{F2558069-0C73-47ba-9BA5-8E591A4EB3EA}"));
			item4.SetupProperty(p => p.AccessClaims, m_FakeClaims);
			item4.SetupProperty(p => p.Properties, m_FakeProps);
			m_FakeItems.Add(item4.Object);

			#endregion
		}

		/// <summary>
		/// Gets the name used for this Fake Repository.
		/// </summary>
		/// <value>The name of this fake repository.</value>
		public string Name { get { return m_RepoName; } }

		#region IItemRepository Members

		public IEnumerable<IItemInstance> GetItem(Guid id, LoadOptions opt)
		{
			return m_FakeItems.OrderBy((i) => String.Format("{0}-{1}", i.Id, i.Version)).Where((i) => (i.Id == id)).AsQueryable<IItemInstance>();
		}

		public IItemInstance GetItem(Guid id, int version, LoadOptions opt)
		{
			return m_FakeItems.Find((i) => (i.Id == id) && (i.Version == version));
		}

		public IEnumerable<IItemInstance> FindByParent(Guid parentId, bool includeIndirect, LoadOptions opt)
		{
			return m_FakeItems.FindAll((i) => i.ParentId == parentId).AsQueryable<IItemInstance>();
		}

		public IItemInstance SaveItem(IItemInstance item, ItemChangeCollection changeCollection) //, RequestTypes requestType)
		{
			m_FakeItems.Add(item);
			return item;
		}

		public IEnumerable<IItemInstance> FindByName(Guid parentId, string name, LoadOptions opt)
		{
			return  m_FakeItems.FindAll((i) => i.ParentId == parentId && i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)).AsQueryable<IItemInstance>();
		}

		public IProviderType FindResourceType(string name)
		{
			return m_FakeProviderTypes.FindAll((r) => r.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)).First();
		}

		public void RemoveItem(Guid id)
		{
            m_FakeItems.Remove(m_FakeItems.Find((i) => (i.Id == id)));
		}

		public void RemoveItem(Guid id, int version)
		{
            m_FakeItems.Remove(m_FakeItems.Find((i) => (i.Id == id) && (i.Version == version)));
		}

		public IEnumerable<IItemInstance> FindSimilar(IItemInstance item, MetaCollection.Framework.Model.LoadOptions opt)
		{
          throw new NotImplementedException(); 
		}
		#endregion
	}
}
